package server.game;

import java.util.ArrayList;
import java.util.Iterator;

import server.controller.ActiveSessions;
import server.controller.ClientSession;
import server.controller.OutboundMessages;
import server.util.Logger;
import shared.util.Config;

/**
 * The Class GameClientCombiner
 * - finds clients for a new game.
 */
public class GameClientCombiner extends Thread {

	/** The active sessions list. */
	ActiveSessions activeSessions;
	
	/** The outboundMessages object. */
	OutboundMessages outQueue;
	
	/** The list of clients for a new game. */
	ArrayList<ClientSession> forGame = new ArrayList<ClientSession>();
	
	/** The game id, increments by 1 after each new game created. */
	int gameId = 0;
	
	/** The logger for logging errors. */
	Logger logger;
	
	/** The configuration object. */
	Config config;

	/**
	 * Instantiates a new game client combiner.
	 *
	 * @param activeSessions the active sessions list
	 * @param outQueue the outboundMessages object
	 * @param logger the logger for logging error messages
	 * @param config the configuration object
	 */
	public GameClientCombiner(ActiveSessions activeSessions,
			OutboundMessages outQueue, Logger logger, Config config) {
		this.activeSessions = activeSessions;
		this.outQueue = outQueue;
		this.logger = logger;
		this.config = config;
		start();
	}

	/** Finds players not in game and starts a new game
	 * @see java.lang.Thread#run()
	 */
	public void run() {
		while (true) {
			synchronized (activeSessions) {
				Iterator<ClientSession> itr = activeSessions.iterator();
				while (itr.hasNext()) {
					ClientSession cli = (ClientSession) itr.next();
					if (!cli.getInGame()) {
						forGame.add(cli);
						cli.setInGame();
					}
					if (forGame.size() == 3) {
						if(!checkAlive()){
							break;
						}
						new GameStarter(forGame, outQueue, gameId++, logger, config);	
						forGame.clear();
						break;
					}
				}
			}
		}
	}
	
	/**
	 * Check alive
	 * - if the player has disconnected, removes him from 
	 * the forGame.
	 *
	 * @return true, if successful
	 */
	private boolean checkAlive(){
		try {
			Thread.sleep(300);
		} catch (InterruptedException e) {
			logger.logError("GameClientCombiner - checkAlive() - sleep interrupted");
		}
		boolean ok = true;
		Iterator<ClientSession> itr = forGame.iterator();
		while(itr.hasNext()){
			ClientSession cli = (ClientSession) itr.next();
			if (!cli.isAlive()) {
				itr.remove();
				ok = false;
			}
		}
		return ok;
	}
}
